﻿#include "Sha.h"
#include "XyNet/Crypto/CryptoPP.h"

namespace XyNet
{
	Sha::DigestType Sha::_defaultDigestType = Sha256;

	Sha::Sha(DigestType digestType)
	{
		setDigestType(digestType);
	}

	Sha::DigestType Sha::getDigestType() const
	{
		assert(_digestType != ShaDefault);
		return _digestType;
	}

	void Sha::setDigestType(DigestType digestType)
	{
		if (digestType == ShaDefault)
			_digestType = _defaultDigestType;
		else
			_digestType = digestType;
	}

	int Sha::getDigestByteLength() const
	{
		return getDigestType() / 8;
	}

	int Sha::getDigestBitLength() const
	{
		return getDigestType();
	}

	Bytes Sha::calculateDigest(const Bytes& input) const
	{
		using namespace CryptoPP;
		unique_ptr<HashTransformation> sha;	// 每次都用新的不会出错

		switch (_digestType)
		{
		case Sha1:
			sha = make_unique<SHA1>();
			break;
		case Sha256:
			sha = make_unique<SHA256>();
			break;
		case Sha384:
			sha = make_unique<SHA384>();
			break;
		case Sha512:
			sha = make_unique<SHA512>();
			break;
		default:
			assert(false);
		}

		Bytes digest(getDigestByteLength(), 0);
		sha->CalculateDigest((byte*)digest.data(), (byte*)input.data(), input.size());
		return digest;
	}

	Sha::DigestType Sha::getDefaultDigestType()
	{
		return _defaultDigestType;
	}

	void Sha::setDefaultDigestType(DigestType digestType)
	{
		assert(digestType != ShaDefault);
		_defaultDigestType = digestType;
	}
}